package com.yituo.mjworld.mvc.action.user;

import com.alibaba.fastjson.JSONObject;
import com.yituo.mjworld.core.annotation.*;
import com.yituo.mjworld.core.utils.Constant;
import com.yituo.mjworld.core.utils.JwtTool;
import com.yituo.mjworld.core.utils.OtherTool;
import com.yituo.mjworld.core.utils.Payload;
import com.yituo.mjworld.core.web.core.MyHttpRequest;
import com.yituo.mjworld.core.web.core.MyHttpResponse;
import com.yituo.mjworld.core.web.core.Result;
import com.yituo.mjworld.mvc.action.IBaseAction;
import com.yituo.mjworld.mvc.entity.UserData;
import com.yituo.mjworld.mvc.entity.other.MoblieCode;
import com.yituo.mjworld.mvc.entity.web.OtherToken;
import com.yituo.mjworld.mvc.entity.web.UserRole;
import com.yituo.mjworld.mvc.entity.web.WebUser;
import com.yituo.mjworld.mvc.entity.web.WxUserinfo;
import com.yituo.mjworld.mvc.form.DeleteForm;
import com.yituo.mjworld.mvc.form.QueryForm;
import com.yituo.mjworld.mvc.form.support.user.Login;
import com.yituo.mjworld.mvc.form.support.user.QueryUser;
import com.yituo.mjworld.mvc.form.support.user.UpdatePassword;
import com.yituo.mjworld.mvc.service.impl.UserServiceImpl;
import com.yituo.mjworld.mvc.service.impl.WxServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Date;

/**
 * 用户模块
 *
 * @author xq
 */
@Component
public class UserAction implements IBaseAction {

  @Autowired
  UserServiceImpl userService;

  @Autowired
  WxServiceImpl wxService;

  {
    // 其他的代理只能获取自己的二维码,而该二维码由各级分销人员去创建.
  }

  /**
   * 使用手机号码结合短信验证码的方式进行登录.
   * <p>
   * 校验不通过无法登录!
   * 登录成功返回token!
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @NoToken
  public void mobileLogin(MyHttpRequest req, MyHttpResponse res) throws IOException {
    String mobile = req.getParameter("mobile");
    String code = req.getParameter("code");
    String ref = req.getParameter("ref");
    // 验证参数
    if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(code)) {
      res.failed("参数不能为空!");
      return;
    }
    // 推荐人是否存在于数据库
    WebUser reffer = null;
    if (!StringUtils.isEmpty(ref)) {
      reffer = userService.getUserByUserId(ref);
      if (reffer == null) {
        res.failed("推荐人不存在!");
        return;
      }
    }
    // 验证验证码,验证码通过,该用户如果存在则直接允许登录.该用户不存在,则先创建用户,并登录.
    // 验证码不通过,
    MoblieCode data = UserData.getMoblieCodeMap().get("mobole");
    if (data == null) {
      res.failed("手机验证码不存在!");
      return;
    } else {
      if (!data.getCode().equals(code)) {
        res.failed("两次输入不匹配!");
        return;
      }
    }
    WebUser webUser = this.userService.bindUserForMobile(ref, mobile);
    String token = JwtTool.createToken(new Payload().setUserId(webUser.getId()).setUserType(webUser.getRule() + ""));
    res.success(token);
  }

  /**
   * 微信登录接口.
   * <p>
   * 前端调起微信授权页面后,微信服务器会将页面重定向wxLogin.html页.
   * <p>
   * 该页面的url上携带有微信服务器后续获取用户信息的参数
   * <p>
   * 该页面会自动创建一个虚拟表单并请求此接口
   * <p>
   * 该接口会获取到用户信息并重定向到前端页.
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @NoToken
  public void wxLogin(MyHttpRequest req, MyHttpResponse res) throws IOException {
    String url = Constant.getDomain();
    // 1.参数校验
    String code = req.getParameter("code");
    String state = req.getParameter("state");
    System.out.println("code:" + code + "\tstate:" + state);
    if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) {
      res.sendRedirect(url + "goto/error.html?msg=parammiss");
      return;
    }

    // 1.网页用户授权登录--->由前端页面跳转微信服务器后回调完成

    // 2.获取accessToken
    JSONObject result = wxService.getWxAccessToken(code);
    String openId = null;
    String accessToken = null;
    if (!StringUtils.isEmpty(result.getString("errmsg"))) {
      res.failed(result.getString("errmsg"));
      return;
    } else {
      openId = result.getString("openid");
      accessToken = result.getString("access_token");
    }
    // 3.刷新accessToken(可跳过)

    // 4.拉取用户信息
    JSONObject wxUserInfoJson = wxService.getWxUserInfo(accessToken, openId);
    if (!StringUtils.isEmpty(wxUserInfoJson.getString("errmsg"))) {
      res.failed(wxUserInfoJson.getString("errmsg"));
      return;
    }
    // 5. 创建微信用户并绑定推荐人
    System.out.println(wxUserInfoJson);
    WxUserinfo wxUserinfo = new WxUserinfo();

    try {
      BeanUtils.populate(wxUserinfo, wxUserInfoJson);
      String userId = this.userService.bindUser(state, wxUserinfo);
      // 6.缓存这个code,用于重定向后申请token
      UserData.getCode().add(code);
      // 7.重定向到首页,首页会通过code来换取本站token
//      res.sendRedirect(url + "#/login?code=" + code + "&uid=" + userId);
//      res.sendRedirect(url + "goto/index.html?code=" + code + "&uid=" + userId);
      //http://imopei.95by.cn/?a=1&b=2?#/login
      res.sendRedirect(url + "?#/login?code=" + code + "&uid=" + userId);
    } catch (Exception e) {
      // 错误处理
      e.printStackTrace();
      res.sendRedirect(url + "goto/error.html?msg=" + e.getMessage());
    }
    return;
  }

  @NoToken
  @Rule(name = "mobile", name_zn = "手机号码", mobile = true)
  public void mobileIsExits(MyHttpRequest req, MyHttpResponse res) throws IOException {
    String mobile = req.getParameter("mobile");
    res.success(this.userService.mobileIsExits(mobile));
  }

//  @Test
//  public void test() {
//    // 查看用户头像url的长度
//    System.out.println("http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46".length());
//  }

  /**
   * 通过code值换取本站颁发的令牌
   */
  @NoToken
  @Rule(name = "code", name_zn = "code")
  public void getTokenByCode(MyHttpRequest req, MyHttpResponse res) throws IOException {
    String code = req.getParameter("code");
    String userId = req.getParameter("uid");
    if (!StringUtils.isEmpty(code) && !StringUtils.isEmpty(userId) && UserData.getCode().contains(code)) {
      WebUser user = this.userService.getUser(userId);
      if (user == null) {
        res.failed("用户不存在!");
        return;
      }
      Payload payload = new Payload();
      payload.setUserId(user.getId()).setUserType(user.getRule() + "").setExp(7 * 24 * 60 * 60 * 1000);
      String token = JwtTool.createToken(payload);
      res.success(token);
      // 移除code
      UserData.getCode().remove(code);
    } else {
      res.failed("bad code!");
    }
  }

  /**
   * 获取用户清单
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @Override
  @Auth(admin_user = true)
  @Check(form = QueryUser.class)
  public void getList(MyHttpRequest req, MyHttpResponse res) throws IOException {
    res.success(this.userService.getList((QueryUser) req.getForm()));
  }

  /**
   * 获取用户的信息
   */
  @Auth(all = true)
  public void getUserInfo(MyHttpRequest req, MyHttpResponse res) throws IOException {
    WebUser user = req.getCurrentUser();
    res.success(userService.getUserInfo(user));
  }

  /**
   * 删除用户
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @Override
  @Ban
  public void delete(MyHttpRequest req, MyHttpResponse res) throws IOException {
//    res.setResult(this.userService.delete((DeleteForm) req.getForm()));
  }

  /**
   * 修改或保存用户
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @Override
  @Check(form = WebUser.class)
  @Auth(admin_user = true)
  public void saveOrUpdate(MyHttpRequest req, MyHttpResponse res) throws IOException {
    res.success(this.userService.delete((DeleteForm) req.getForm()));
  }

  /**
   * 普通用户登录接口
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @NoToken
  @Check(form = Login.class)
  @Auth(admin_user = true)
  public void login(MyHttpRequest req, MyHttpResponse res) throws IOException {
    Login form = (Login) req.getForm();
    WebUser webUser = userService.login(form);
    if (webUser != null) {
      // 生成Token
      Payload payload = new Payload().setUserId(webUser.getId()).setUserType(webUser.getRule() + "").setExp(7 * 24 * 60 * 60 * 1000);
      String token = JwtTool.createToken(payload);
      res.setHeader("token", token);

      // 登录
      OtherToken tokenObj = new OtherToken();
      tokenObj.setToken(token);
      tokenObj.setAccounts(webUser.getAccount());
      tokenObj.setCreateDate(new Date());
      tokenObj.setUserType(UserRole.SUPER_ADMIN);
      tokenObj.setEndDate(new Date(tokenObj.getCreateDate().getTime() + 1000 * 60 * 30));

      // 缓存token
      UserData.putToken(webUser.getAccount(), tokenObj);
      JSONObject result = (JSONObject) JSONObject.toJSON(webUser);

      // 移除密码
      result.remove("password");
      res.success(result);
    } else {
      res.failed("用户名密码错误!");
    }
  }

  /**
   * 创建用户二维码.
   * <p>
   * 目前仅支持超级管理员操作生成相关的推广码
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @Auth(admin_user = true)
  @Check
  public void getUserQRCode(MyHttpRequest req, MyHttpResponse res) throws IOException {
    String userId = null;
    if (UserRole.isSuperAdmin(req.getCurrentUser().getRule())) {
// 超级管理员指定某个用户成为代理用户
      userId = req.getParameter("userId");
    } else {
      userId = req.getCurrentUser().getId();
    }
    String qrCode = this.userService.getUserQrcode(userId);
    if (StringUtils.isEmpty(qrCode)) {
      res.failed("二维码获取失败!请稍后尝试!");
    } else {
      res.success(qrCode);
    }
  }


  /**
   * 获取我的二维码.
   * <p>
   * 目前仅支持超级管理员操作生成相关的推广码
   *
   * @param req
   * @param res
   * @throws IOException
   */
  public void getMyQrCode(MyHttpRequest req, MyHttpResponse res) throws IOException {
    res.success(this.userService.getMyQrCode(req.getCurrentUser()));
  }

  /**
   * 获取用户订单
   * <p>
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @Ban
  @Auth(admin_user = true)
  @Check(form = QueryForm.class)
  public void getUserOrders(MyHttpRequest req, MyHttpResponse res) throws IOException {
    QueryForm form = (QueryForm) req.getForm();
    WebUser currentUser = req.getCurrentUser();
    String userId = req.getParameter("id");
    if (UserRole.isSuperAdmin(currentUser.getRule())) {
      if (StringUtils.isEmpty(userId)) {
        res.failedFor302("请输入您要查询的用户ID!");
        return;
      }
    } else {
      userId = currentUser.getId();
    }
    res.success(userService.getUserOrders(form, userId));
  }

  /**
   * 修改用户密码
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @Check(form = UpdatePassword.class)
  @Auth(admin_user = true)
  public void updatePassword(MyHttpRequest req, MyHttpResponse res) throws IOException {
    UpdatePassword form = (UpdatePassword) req.getForm();
    WebUser user = req.getCurrentUser();
    String userId = req.getParameter("userId");
    if (!UserRole.isSuperAdmin(user.getRule())) {
      if (!user.getId().equals(userId)) {
        res.failedFor404("你没有权限访问该接口!");
        return;
      }
    }
    boolean result = userService.updatePassword(user.getAccount(), form.newPassword);
    if (result) {
      res.success("修改成功!");
    } else {
      res.failed("修改成功!");
    }
  }

  /**
   * 个人详细信息补齐
   *
   * @param req
   * @param res
   * @throws IOException
   */
  @Auth(admin_user = true)
  public void setMyInfo(MyHttpRequest req, MyHttpResponse res) throws IOException {
    // 当前接口的应用场景
    String scene = (String) req.getAttribute("scene");
    String filedName = null;
    String value = null;
    Result result = new Result(false, "接口无对应场景!");
    if (StringUtils.isEmpty(scene)) {
      // 应用场景为默认,则从Paramter中获取到相关的参数,并写入到数据库中
      filedName = req.getParameter("filedName");
      value = req.getParameter("value");
      // 用户信息补齐
      result = userService.setMyInfo(req.getCurrentUser().getId(), filedName, value);
    } else if (scene.equals("upload")) {
      // 应用场景为上传场景,则请求对象是从UploadServlet经过forward转发过来的对象,对应的value百分之百为文件名
      filedName = (String) req.getAttribute("filedName");
      value = (String) req.getAttribute("value");
      result = userService.setMyInfo(req.getCurrentUser().getId(), filedName, value);
      if (!result.getResult()) {
        // 写入失败,则需要删除对应的文件名
        OtherTool.deleteFile(UserData.getUploadPath() + value);
      } else {
        // 写入成功,返回对应的url
        result.setMsg(Constant.getDomain() + "uploadDir/img/" + value);
      }
    }
    res.setResult(result);
  }
}
